package com.john.http.core.util;

import com.john.http.core.security.EmptyX509TrustManager;
import com.john.http.core.security.TrueHostnameVerifier;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.concurrent.TimeUnit;

/**
 * 〈一句话功能简述〉<br/>
 * 〈功能详细描述〉
 *
 * @author jiangguangtao on 2016/4/28.
 */
public class HtmlFetchUtil {
    private static final Logger log = LoggerFactory.getLogger(HtmlFetchUtil.class);
    public static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36";
    public static final int DEFAULT_TIMEOUT = 30;
    private static CloseableHttpClient httpClient = null;

    /**
     * 获取HTMl内容
     *
     * @param url 从哪儿获取HTML
     * @return
     */
    public static String getHtml(String url) {
        return getHtml(url, DEFAULT_TIMEOUT, USER_AGENT, Charset.defaultCharset());
    }

    /**
     * 获取HTMl内容
     *
     * @param url            从哪儿获取HTML
     * @param contentCharset 文档内容编码
     * @return
     */
    public static String getHtml(String url, Charset contentCharset) {
        contentCharset = (null == contentCharset ? Charset.defaultCharset() : contentCharset);
        return getHtml(url, DEFAULT_TIMEOUT, USER_AGENT, contentCharset);
    }

    /**
     * 获取HTMl内容
     *
     * @param url       从哪儿获取HTML
     * @param timeout   连接超时时间 秒
     * @param userAgent 连接User-Agent
     * @return
     */
    private static String getHtml(String url, int timeout, String userAgent, Charset contentCharset) {
        try {
            HttpGet request = new HttpGet(url);
            request.setHeader(HTTP.USER_AGENT, userAgent);
            CloseableHttpClient httpClient = getTrueHttpsClient(timeout);
            CloseableHttpResponse response = httpClient.execute(request);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                log.info("成功从{}获取内容", url);
                return EntityUtils.toString(response.getEntity(), contentCharset);
            } else {
                log.error("请求URL：{} 返回异常状态：{}", url, response.getStatusLine());
                return null;
            }
        } catch (IOException e) {
            log.error("获取内容异常", e);
            return null;
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            log.error("HTTPS连接初始化异常", e);
            return null;
        }
    }


    /**
     * 获取一个HTTPS连接
     *
     * @param timeOutSeconds 连接超时秒数
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    public static CloseableHttpClient getTrueHttpsClient(int timeOutSeconds) throws NoSuchAlgorithmException, KeyManagementException {
        if (null == httpClient) {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(new KeyManager[0], new TrustManager[]{new EmptyX509TrustManager()}, new SecureRandom());
            httpClient = HttpClientBuilder.create()
                    .setSSLContext(sslContext)
                    .setConnectionTimeToLive(timeOutSeconds, TimeUnit.SECONDS)
                    .setSSLHostnameVerifier(new TrueHostnameVerifier())
                    .build();
        }

        return httpClient;
    }

}
